(** 
    Main.ml

    Bozman Çagdas <bozman.cagdas@gmail.com> - 2011
    Razakamiadana Tefin <tefy.razaka@gmail.com>   - 2011
*)
open Ast
open Sets
open Utils

let (>>=) = Lwt.bind

let parse_file file = 
  let rec aux accu file =
    match read file with
      | None -> accu
      | Some line ->
	let req = 
	  Parser.expression Lexer.token (Lexing.from_string (line)) in
	let req = Compact.compact_req_list (list_of_req req) in
	aux (req :: accu) file
  in
  aux [] file
    
let _ =
  if Array.length Sys.argv <> 3 then failwith "Usage: run input_file output_file"
  else
    let input = open_in_file Sys.argv.(1) in
    let ouput = open_out_file Sys.argv.(2) in
    let output_time = open_out (spf "%s_time" Sys.argv.(2)) in
    let output_info = open_out (spf "%s_info" Sys.argv.(2)) in
    let criterias = List.rev (parse_file input) in
    let t = Sys.time () in
    Lwt_main.run
      (Lwt_list.iter_s 			(* Sequential *)
	 (fun criterias ->
	   (Lwt.return (criterias) >>=
	      (fun cs ->
		let stop = ref false in
		Lwt_list.map_p		(* Parallel *)
		  (fun (p_or_l, depth) ->    		    
		    match p_or_l with
		      | P t -> 
			Lwt_preemptive.detach (Depth.dfs t depth) stop >>=
			  (fun s -> 
			    if StringSet.is_empty s then
			      (stop := true; Lwt.return s)
			    else
			      Lwt.return s)
		      | L t -> 
			Lwt_preemptive.detach (Breadth.bfs t depth) stop >>= 
			  (fun s -> 
			    if StringSet.is_empty s then
			      (stop := true; Lwt.return s)
			    else
			      Lwt.return s)
		  )
		  cs) >>=
	      
              (fun sets ->
		match sets with
		  | [] -> Lwt.return StringSet.empty
		  | [ set ] -> Lwt.return set
		  | set :: next -> 
		    Lwt.return (List.fold_left StringSet.inter set next)) >>=

	      (fun set ->
		let _ = write output_time (spf "%f\n" (Sys.time () -. t)) in
		let wl = StringSet.elements set in
		let wl = List.map (fun s -> spf "<%s>" s) wl in
		let res = String.concat ", " wl in
		write ouput (spf "%s\n" res);
		write output_info (spf "Length: %d\n" (StringSet.cardinal set));
		debug "Length : %d \n" (StringSet.cardinal set);
		Lwt.return ())
	   )
	 ) criterias)
      
